home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / serialtc / serial.c next >
Text File  |  1988-02-19  |  6KB  |  243 lines

  1. /*
  2. ==========================
  3. c.language/listings #115, from barryn, 8544 chars, Sat Aug 29 17:17:28 1987
  4. --------------------------
  5. TITLE: Communications routines in Turbo C
  6.  
  7.    The following code shows how to take advantage of some of
  8. the TurboC extensions to the C language to do asynchronous
  9. communications (without having to write supporting assembly-
  10. language routines).  The code was supplied by Peter Ibbotson of
  11. Borland.  After the communications-related functions themselves,
  12. you'll find a small main() section of code that uses those functions
  13. to implement a rudimentary glass-TTY terminal program.  (I say
  14. rudimentary to mean that control characters are not recognized and
  15. there are no file transfer, dialing directory, etc. features.)
  16.  
  17.    First, here's Serial.C:
  18. */
  19.  
  20. /*       SERIAL.C       */
  21.  
  22. #include        "serial.h"
  23. #include        <dos.h>
  24. #include        <stdio.h>
  25. #include        <conio.h>
  26. #include        <bios.h>
  27. #include        <process.h>
  28.  
  29. int SError;
  30. int portbase=0;
  31. void interrupt (*oldvects[2])();
  32. char ccbuf[SBUFSIZ];
  33. int startbuf=0;
  34. int endbuf=0;
  35.  
  36. /*      this does the hard work (handling interrupts)           */
  37.  
  38. void interrupt com_int (void)
  39.  
  40. { disable ();
  41.   if ((inportb (portbase+IIR) & RX_MASK)==RX_ID)
  42.     { if (((endbuf+1) & 0x1fff)==startbuf)
  43.       SError=BUFOVFL;
  44.       ccbuf[endbuf++]=inportb (portbase+RX);
  45.       endbuf&=0x1fff;
  46.     };
  47.   outportb (ICR,EOI);
  48.   enable ();
  49. }
  50.  
  51. /* this routine returns the currently value in the buffer */
  52.  
  53. int getccb(void)
  54.  
  55. { int res;
  56.   if (endbuf==startbuf) return (-1);
  57.   res=(int) ccbuf[startbuf];
  58.   startbuf=(startbuf+1) % SBUFSIZ;
  59.   return (res);
  60. }
  61.  
  62. void setvects (void)
  63.  
  64. { oldvects[0]=getvect(0x0b);
  65.   oldvects[1]=getvect(0x0c);
  66.   setvect(0x0b,com_int);
  67.   setvect(0x0c,com_int);
  68. }
  69.  
  70. void resvects (void)
  71.  
  72. { setvect(0x0b,oldvects[0]);
  73.   setvect(0x0c,oldvects[1]);
  74. }
  75.  
  76. void i_enable (int pnum)
  77.  
  78. { int c;
  79.   disable();
  80.   c = inportb (portbase+MCR) | MC_INT;
  81.   outportb (portbase+MCR,c);
  82.   outportb (portbase+IER,RX_INT);
  83.   c = inportb (IMR) & (pnum==2 ? IRQ3 : IRQ4);
  84.   outportb (IMR,c);
  85.   enable();
  86. }
  87.  
  88. void i_disable (void)
  89.  
  90. { int c;
  91.   disable ();
  92.   c=inportb (IMR) | ~IRQ3 | ~IRQ4;
  93.   outportb (IMR,c);
  94.   outportb (portbase + IER,0);
  95.   c=inportb (portbase+MCR) & ~MC_INT;
  96.   outportb (portbase+MCR,c);
  97.   enable ();
  98. }
  99.  
  100. void comon (void)
  101.  
  102. {  int c,pnum;
  103.    pnum = portbase == COM1BASE ? 1 : 2;
  104.    i_enable (pnum);
  105.    c=inportb (portbase + MCR) | DTR | RTS;
  106.    outportb (portbase + MCR,c);
  107. }
  108.  
  109. void initserial (void)
  110.  
  111. { endbuf=startbuf=0;
  112.   setvects();
  113.   comon();
  114. };
  115.  
  116. void comoff (void)
  117.  
  118. { i_disable ();
  119.   outportb (portbase+MCR,0);
  120. }
  121.  
  122. void closeserial(void)
  123.  
  124. { comoff();
  125.   resvects();
  126. };
  127.  
  128. /* this outputs a serial character              */
  129.  
  130. int SerialOut (char x)
  131.  
  132. { long timeout = 0x0000ffff;
  133.   outportb (portbase+MCR,OUT2|DTR|RTS);
  134.   /* wait for clear to send     */
  135.   while ((inportb(portbase + MSR) & CTS)==0)
  136.     if ((--timeout)==0) return (-1);
  137.   timeout=0x0000ffff;
  138.   /* wait for outport register to clear         */
  139.   while ((inportb(portbase+LSR) & DSR)==0)
  140.     if ((--timeout)==0) return (-1);
  141.   disable ();
  142.   outportb (portbase+TX,x);
  143.   enable ();
  144.   return (0);
  145. }
  146.  
  147. /* this routine sets which port we are working with     */
  148.  
  149. int SetPort (int Port)
  150.  
  151. { int far * RS232_Addr;
  152.   int Offset;
  153.  
  154.   switch (Port)                         /* sort out the base address    */
  155.   { case 1 : Offset=0x0000; break;      /* only ports one & two allowed */
  156.     case 2 : Offset=0x0002; break;
  157.     default : return (-1);
  158.   };
  159.   RS232_Addr=MK_FP(0x0040,Offset);      /* find out where the port is   */
  160.   if (*RS232_Addr==0) return (-1);      /* if it ain't there return (-1)*/
  161.   portbase=*RS232_Addr;                 /* otherwise set portbase       */
  162.   return (0);
  163. }
  164.  
  165. /* this routine sets the speed; will accept funny baud rates   */
  166.  
  167. int SetSpeed (int Speed)
  168.  
  169. { char c;
  170.   int divisor;
  171.   if (Speed==0) return (-1);            /* avoid divide by zero */
  172.   else divisor=(int)(115200L/Speed);
  173.   if (portbase==0) return (-11);
  174.   disable ();
  175.   c=inportb (portbase+LCR);
  176.   outportb (portbase+LCR,(c|0x80));                     /* set DLAB     */
  177.   outportb (portbase+DLL,(divisor & 0x00ff));   /* set divisor  */
  178.   outportb (portbase+DLH,((divisor>>8)&0x00ff));
  179.   outportb (portbase+LCR,c);
  180.   enable();
  181.   return (0);
  182. }
  183.  
  184. /*      This routine set the LCR                */
  185.  
  186. int SetOthers (int Parity,int Bits,int StopBit)
  187.  
  188. { int temp;
  189.   if (portbase==0) return (-1);
  190.   if ((Parity<NO_PAR) || (Parity>OD_PAR)) return (-1);
  191.   if ((Bits<5) || (Bits>8)) return (-1);
  192.   if ((StopBit<1) || (StopBit>2)) return (-1);
  193.   temp=Bits-5;
  194.   temp|=((StopBit==1) ? 0x00 : 0x04);
  195.   switch (Parity)
  196.   { case NO_PAR : temp |= 0x00; break;
  197.     case OD_PAR : temp |= 0x08; break;
  198.     case EV_PAR : temp |= 0x18; break;
  199.   }
  200.   disable();            /* turn off interrupts */
  201.   outportb (portbase+LCR,temp);
  202.   enable();             /* turn em back on */
  203.   return (0);
  204. }
  205.  
  206. /*      This routine sets the ports                     */
  207.  
  208. int setserial (int Port,int Speed,int Parity,int Bits,int StopBit)
  209.  
  210. { if (SetPort(Port)==-1) return(-1);
  211.   if (SetSpeed(Speed)==-1) return(-1);
  212.   if (SetOthers(Parity,Bits,StopBit)==-1) return (-1);
  213.   return (0);
  214. }
  215.  
  216. /* short demo                                           */
  217. /* this opens the ports and echos to screen until       */
  218. /* ESCape received                                      */
  219.  
  220. main ()
  221.  
  222. { int c;
  223.  
  224.   if (setserial (COM1,2400,NO_PAR,8,1) ==-1) exit (1);
  225.   initserial();
  226.   printf("You're now in terminal mode.  Press ESC to quit the program.\n\n");
  227.  
  228. do {
  229.     if (kbhit()) {
  230.         c = getch();
  231.         if (c==27)
  232.             break;
  233.         SerialOut(c);
  234.         }
  235.  
  236.     if ((c=getccb())!=-1)
  237.        putchar (c);
  238.  
  239.     } while (c!=27);
  240.  
  241.     closeserial();
  242. }
  243.